﻿import React from 'react'
import * as PropTypes from 'prop-types'
import classNames from 'classnames'
import {Button} from '@/components/Button'
import {RenderInBody} from './RenderInBody'
import {ModalStore} from './ModalStore'
import {StoreManager} from '@/stores'
import {observer} from 'mobx-react'
import {Slot} from '@/components/Slot'
import ModalExtensions from './ModalExtensions'

/**
 * 模式对话框组件
 */
@observer
export class Modal extends React.Component {

    static propTypes = {
        name: PropTypes.oneOfType([PropTypes.string, PropTypes.symbol]).isRequired,
        className: PropTypes.string,
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
        height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
        top: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
        left: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
        active: PropTypes.bool,
        overlayerClose: PropTypes.bool,
        renderInBody: PropTypes.bool,
        showHeader: PropTypes.bool,
        showFooter: PropTypes.bool,
        showCancel: PropTypes.bool,
        showOverlayer: PropTypes.bool,
        okText: PropTypes.string,
        cancelText: PropTypes.string,
        onClose: PropTypes.func,
        onCancel: PropTypes.func,
        onOk: PropTypes.func
    }

    static defaultProps = {
        width: 500,
        showCancel: true,
        showFooter: true,
        showHeader: true,
        showOverlayer: true,
        renderInBody: true,
        okText: '确定',
        cancelText: '取消'
    }

    constructor(props) {
        super(props);
        this.store = StoreManager.create(new ModalStore(props))
        this.confirmButonName = Symbol(`ConfirmButton`)
    }

    componentWillUnmount() {
        StoreManager.delete(this.store)
    }

    handleCancel(event) {
        const {onCancel} = this.props
        const result = onCancel && onCancel(event)
        if (result === false) {
            return
        } else if (result instanceof Promise) {
            result.then(state => {
                if (state !== false) {
                    this.close(event)
                }
            })
        } else {
            this.close(event)
        }
    }

    handleOverlayer(event) {
        this.props.overlayerClose && this.handleCancel(event)
    }

    handleOk(event) {
        const {
            onOk
        } = this.props
        const result = onOk && onOk(event)
        if (result instanceof Promise) {
            return new Promise(resolve => {
                if (result instanceof Promise) {
                    result.then(() => {
                        resolve()
                        this.close(event)
                    })
                }
            })
        } else {
            this.close(event)
        }

    }

    close(event) {
        const {
            onClose
        } = this.props
        this.store.hideAsync(200).then(() => {
            onClose && onClose(event)
        })
    }

    renderOverlayer() {
        const {
            showOverlayer
        } = this.props
        const {overlayerActive} = this.store
        if (!showOverlayer) {
            return null
        }
        return <div className={classNames("modal-overlayer", {active: overlayerActive})}
                    onClick={this.handleOverlayer.bind(this)}></div>
    }

    renderHeader() {
        const {
            showHeader,
            children
        } = this.props
        if (!showHeader) {
            return null
        }
        return <Slot name="header" className='modal-header' content={children}></Slot>
    }

    renderFooter() {
        const {
            //name,
            cancelText,
            okText,
            showFooter,
            showCancel,
            children
        } = this.props
        if (!showFooter) {
            return null
        }
        const buttonStore = StoreManager.get(this.confirmButonName, {})
        return <Slot name="footer" className={classNames('modal-buttons')} content={children}>
            {showCancel ? <Button type="default" onClick={this.handleCancel.bind(this)}
                                  disabled={buttonStore.loading}>{cancelText}</Button> : null}
            <Button name={this.confirmButonName} type="primary" onClick={this.handleOk.bind(this)}>{okText}</Button>
        </Slot>
    }

    renderModal() {
        const {
            className,
            children
        } = this.props
        const store = this.store

        return <div className={classNames("modal", className, store.classNames)} style={store.styles}>
            {this.renderHeader()}
            <Slot className='modal-content' content={children}/>
            {this.renderFooter()}
        </div>
    }

    static confirm(props) {
        return ModalExtensions.confirm(props)
    }

    static success(content, props) {
        return ModalExtensions.success(content, props)
    }

    static alert(content, props) {
        return ModalExtensions.alert(content, props)
    }

    static info(content, props) {
        return ModalExtensions.info(content, props)
    }

    static warn(content, props) {
        return ModalExtensions.warn(content, props)
    }

    static error(content, props) {
        return ModalExtensions.error(content, props)
    }

    render() {
        const {
            renderInBody
        } = this.props
        const store = this.store
        if (renderInBody) {
            return (<RenderInBody className={classNames("madal-wrapper")} active={store.active}>
                {this.renderOverlayer()}
                {this.renderModal()}
            </RenderInBody>)
        }
        return (
            <div className={classNames("madal-wrapper", {active: store.active})}>
                {this.renderOverlayer()}
                {this.renderModal()}
            </div>)
    }
}


